Receiving Events
You receive events by calling an Event Manager routine, usuallyWaitNextEvent
. When you ask for an event, the Event Manager returns the next available event according to its event priority. The Event Manager returns events in this order of priority:
To retrieve an event, you pass the
- activate events
- mouse-down, mouse-up, key-down, key-up, and disk-inserted events in FIFO (first-in, first-out) order
- auto-key events
- update events (in front-to-back order of windows)
- operating-system events (suspend, resume, mouse-moved)
- high-level events
- null events
WaitNextEvent
function an event record, defined by theEventRecord
data type:
TYPE EventRecord = RECORD what: Integer; {event code} message: LongInt; {event message} when: LongInt; {ticks since startup} where: Point; {mouse location} modifiers: Integer; {modifier flags} END;On return fromWaitNextEvent
, thewhat
field of the event record contains an integer that specifies the type of event received. The Event Manager uses this set of predefined constants to indicate the event type:
CONST nullEvent = 0; {no other pending events} mouseDown = 1; {mouse button pressed} mouseUp = 2; {mouse button released} keyDown = 3; {key pressed} keyUp = 4; {key released} autoKey = 5; {key held down} updateEvt = 6; {a window needs updating} diskEvt = 7; {disk inserted} activateEvt = 8; {activate/deactivate window} osEvt = 15; {operating-system event} kHighLevelEvent = 23; {high-level event}Themessage
field of the event record contains additional information about the event. The interpretation of this field depends on the type of event you've received. For some events (such as null events, mouse-up, and mouse-down events), the value in themessage
field is undefined. For keyboard events, themessage
field indicates which key was pressed. For activate and update events, themessage
field contains a window pointer to the affected window. For disk-inserted events, themessage
field contains the drive number in the low-order word and the result code of the File Manager's attempt to mount that disk in that drive. Listing 4-3 illustrates how an application reads parts of themessage
field while handling disk-inserted events.Listing 4-3 Handling disk-inserted events
PROCEDURE DoDiskEvent (myEvent: EventRecord); VAR myResult: Integer; myPoint: Point; BEGIN IF HiWord(myEvent.message) <> noErr THEN BEGIN SetPt(myPoint, 100, 100); myResult := DIBadMount(myPoint, myEvent.message); END; END;If the disk was not successfully mounted (that is, if the high-order word of themessage
field does not containnoErr
), thenDoDiskEvent
calls the system software routineDIBadMount
to inform the user and allow the disk to be ejected or reformatted. (See the chapter "Disk Initialization Manager" in Inside Macintosh: Files for more information about handling disk-inserted events.)The
where
field of the event record contains, for low-level events, the location of the cursor at the time the event was posted. You can use this information to determine where on the screen a mouse-down event occurred, for instance.The
modifiers
field contains information about the state of the modifier keys and the mouse button at the time the event was posted. For activate events, this field also indicates whether the window should be activated or deactivated. (In System 7, it also indicates whether a mouse-down event caused your application to switch to the foreground.)To handle an event, you simply take whatever action is appropriate for the kind of event it is. Listing 4-4 shows one way to structure an event-handling routine.
PROCEDURE DoMainEventLoop; VAR myEvent: EventRecord; gotEvent: Boolean; {is returned event for me?} BEGIN REPEAT gotEvent := WaitNextEvent(everyEvent, myEvent, 15, NIL); IF NOT DoHandleDialogEvent(myEvent) THEN IF gotEvent THEN BEGIN CASE myEvent.what OF mouseDown: DoMouseDown(myEvent); {see page 120} keyDown, autoKey: DoKeyDown(myEvent); {see page 160} updateEvt: DoUpdate(WindowPtr(myEvent.message)); {see page 124} diskEvt: DoDiskEvent(myEvent); {see page 77} activateEvt: DoActivate(WindowPtr(myEvent.message), myEvent.modifiers); {see page 126} osEvt: DoOSEvent(myEvent); {see page 171} keyUp, mouseUp: ; nullEvent: DoIdle(myEvent); {see page 173} OTHERWISE ; END; {CASE} END ELSE DoIdle(myEvent); UNTIL gDone; {loop until user quits} END;The event loop defined in Listing 4-4 repeatedly calls theWaitNextEvent
function to retrieve the next available event. This function returns a value ofFALSE
if there are no events of the desired type (other than null events) pending for your application. Otherwise,WaitNextEvent
returnsTRUE
.After the next available event is retrieved, the
DoMainEventLoop
procedure calls the application-defined functionDoHandleDialogEvent
(defined in Listing 7-5 on page 141) to determine whether the event applies to a dialog box. TheDoHandleDialogEvent
function returnsTRUE
if it handled the event andFALSE
otherwise.
If the event retrieved does not apply to a dialog box, and if it isn't a null event, then
- Note
- Dialog boxes receive special treatment because the system software automatically handles many user actions in dialog boxes. For example, the Dialog Manager handles update events for dialog boxes, and it calls the Control Manager to handle user actions affecting any controls in the dialog box.
![]()
DoMainEventLoop
branches into a PascalCASE
statement in which the labels are simply the predefined constants for each event type. As you can see, the event loop calls an application-defined routine to handle each particular kind of event. These routines are defined throughout this book.